<?php
/*
 * This file is part of the BooXtore Student project.
 *
 * (c) Francis Backeland f.backeland@gmail.com
 * (c) Laurine Chaplot chaplot.laurine@orange.fr
 * (c) Julien Dutot julien.dutot@gmail.com
 * (c) Romain Guillaume romain-guillaume@orange.fr
 * (c) Guillaume Paringaux g.paringaux@gmail.com
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code
 * 
 */
namespace BXTR\DatatablesBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
 * Transform an entity in a provided ArrayCollection fetched with doctrine to a number, the identifier.
 */
class EntityToNumberTransformer implements DataTransformerInterface
{
    /**
     * Doctrine class name
     *
     * @var String
     */
    private $className;

    /**
     * @var ArrayCollection
     */
    private $queryBuilder;

    /**
     * @param ArrayCollection $collection
     * @param String $index index field
     */
    public function __construct($queryBuilder)
    {
        $this->queryBuilder = $queryBuilder;
    }

    /**
     * Transforms an entity to a string (number) using the collection provided.
     *
     * @param Object|null $entity
     * @return string
     */
    public function transform($entity)
    {
        if (null === $entity) {
            return "";
        }

        $accessor = PropertyAccess::createPropertyAccessor();

        $identifier = $this->getEntityIdentifier();
        return $accessor->getValue($entity, $identifier);
    }

    /**
     * Give the primary identifier of the entity.
     * The primary identifier is the name of the field defined in the id 
     * section of the mapping file.
     * @TODO: This will not work with multiple identifiers.
     */
    private function getEntityIdentifier()
    {
        $qb = $this->queryBuilder;

        $em = $qb->getEntityManager();
        return $em->getClassMetadata($qb->getRootEntities()[0])->identifier[0];
    }

    /**
     * Transforms a string (number) to an object (entity).
     *
     * @param  string $number
     * @return Object|null
     * @throws TransformationFailedException if object is not found.
     */
    public function reverseTransform($number)
    {
        if (!$number) {
            return null;
        }
        
        $entity = null;

        $qb = $this->queryBuilder;

        $identifier = $this->getEntityIdentifier();

        try {
            $entity = $qb
                ->andWhere($qb->expr()->eq($qb->getRootAliases()[0] . '.' . $identifier, ':id'))
                ->setParameters(array('id' => $number))
                ->getQuery()
                ->getSingleResult();
        } catch (\Doctrine\ORM\NoResultException $e) {
            $entity = null;
        }

        if (null === $entity) {
            throw new TransformationFailedException(sprintf(
                'Unable to find the entity with id "%s" with the queryBuilder provided!',
                $number
            ));
        }

        return $entity;
    }
}
